{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b272a181",
   "metadata": {},
   "source": [
    "# LangChain Agent with Ollama"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "49f28dec-2b62-4c0b-8ba6-b1236ed011c4",
   "metadata": {},
   "source": [
    "## 💡 This agent shows how to:\n",
    "• Build a simple but complete agent using LangChain and Ollama\n",
    "\n",
    "• Replace OpenAI models with Ollama in LangChain\n",
    "\n",
    "• Chain multiple LLM calls together\n",
    "\n",
    "• Build structured workflows\n",
    "\n",
    "• Handle different types of analysis tasks\n",
    "\n",
    "• Quick and clear way to showcase the agent’s ability to interpret and analyze various kinds of textual input."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ba0679e4-deb0-4862-bf94-8a7a6631175e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import asyncio\n",
    "from typing import Dict, List\n",
    "from langchain_community.chat_models import ChatOllama\n",
    "from langchain.prompts import ChatPromptTemplate\n",
    "from langchain.schema import HumanMessage, SystemMessage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8dcbf815-d01f-4a77-8def-8587d9903fda",
   "metadata": {},
   "outputs": [],
   "source": [
    "class SimpleAnalysisAgent:\n",
    "    \"\"\"A simple agent that analyzes text and provides insights.\"\"\"\n",
    "    \n",
    "    def __init__(self, model_name: str = \"llama3.1:8b\"):\n",
    "        if not self.check_ollama_model(model_name):\n",
    "            print(f\"❌ Model {model_name} not found. Try: ollama pull {model_name}\")\n",
    "            raise ValueError(f\"Model {model_name} not available\")\n",
    "        \n",
    "        self.llm = ChatOllama(model=model_name, temperature=0.1)\n",
    "        self.conversation_history = []\n",
    "    \n",
    "    def classify_text(self, text: str) -> str:\n",
    "        \"\"\"Classify the type of text.\"\"\"\n",
    "        prompt = ChatPromptTemplate.from_messages([\n",
    "            (\"system\", \"Classify this text as one of: news, blog, email, code, academic, or other. Respond with just the category.\"),\n",
    "            (\"human\", \"{text}\")\n",
    "        ])\n",
    "        \n",
    "        chain = prompt | self.llm\n",
    "        result = chain.invoke({\"text\": text[:500]})  # Limit length\n",
    "        return result.content.strip().lower()\n",
    "    \n",
    "    def extract_key_points(self, text: str) -> List[str]:\n",
    "        \"\"\"Extract key points from text.\"\"\"\n",
    "        prompt = ChatPromptTemplate.from_messages([\n",
    "            (\"system\", \"Extract 3-5 key points from this text. Return as a simple numbered list.\"),\n",
    "            (\"human\", \"{text}\")\n",
    "        ])\n",
    "        \n",
    "        chain = prompt | self.llm\n",
    "        result = chain.invoke({\"text\": text})\n",
    "        \n",
    "        # Parse the numbered list\n",
    "        lines = result.content.strip().split('\\n')\n",
    "        points = [line.strip() for line in lines if line.strip() and any(c.isdigit() for c in line[:3])]\n",
    "        return points[:5]  # Limit to 5 points\n",
    "    \n",
    "    def summarize(self, text: str) -> str:\n",
    "        \"\"\"Create a summary of the text.\"\"\"\n",
    "        prompt = ChatPromptTemplate.from_messages([\n",
    "            (\"system\", \"Summarize this text in 2-3 sentences. Be concise and clear.\"),\n",
    "            (\"human\", \"{text}\")\n",
    "        ])\n",
    "        \n",
    "        chain = prompt | self.llm\n",
    "        result = chain.invoke({\"text\": text})\n",
    "        return result.content.strip()\n",
    "    \n",
    "    def analyze_text(self, text: str) -> Dict:\n",
    "        \"\"\"Complete analysis of text.\"\"\"\n",
    "        print(f\"🔍 Analyzing text ({len(text)} characters)...\")\n",
    "        \n",
    "        # Step 1: Classify\n",
    "        print(\"  📊 Classifying...\")\n",
    "        category = self.classify_text(text)\n",
    "        \n",
    "        # Step 2: Extract key points\n",
    "        print(\"  🔑 Extracting key points...\")\n",
    "        key_points = self.extract_key_points(text)\n",
    "        \n",
    "        # Step 3: Summarize\n",
    "        print(\"  📝 Summarizing...\")\n",
    "        summary = self.summarize(text)\n",
    "        \n",
    "        return {\n",
    "            \"category\": category,\n",
    "            \"key_points\": key_points,\n",
    "            \"summary\": summary,\n",
    "            \"length\": len(text)\n",
    "        }\n",
    "    \n",
    "    @staticmethod\n",
    "    def check_ollama_model(model_name: str) -> bool:\n",
    "        try:\n",
    "            import requests\n",
    "            response = requests.get(\"http://localhost:11434/api/tags\")\n",
    "            models = [m[\"name\"] for m in response.json().get(\"models\", [])]\n",
    "            return model_name in models\n",
    "        except:\n",
    "            return False"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "458d3849-e956-450d-a849-9f08624f7a6e",
   "metadata": {},
   "source": [
    "# Demo agent:\n",
    "\n",
    "The demo_agent() function is used to demonstrate the text analysis agent in action. A set of predefined sample texts is provided, each representing different content types (e.g., a news article or a code snippet).\n",
    "\n",
    "The function processes each sample and displays the results, including:\n",
    "\n",
    "• Detected content category\n",
    "\n",
    "• Summary of the text\n",
    "\n",
    "• List of extracted key points\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6158f4b3-ddd9-4319-945c-7cf45644d1fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "def demo_agent():\n",
    "    \"\"\"Demonstrate the agent with sample texts.\"\"\"\n",
    "    print(\"🤖 LangChain Agent with Ollama Demo\")\n",
    "    print(\"=\" * 40)\n",
    "    \n",
    "    try:\n",
    "        agent = SimpleAnalysisAgent()\n",
    "        print(\"✅ Agent initialized successfully\\n\")\n",
    "    except ValueError as e:\n",
    "        print(e)\n",
    "        return\n",
    "    \n",
    "    # Sample texts to analyze\n",
    "    samples = [\n",
    "        {\n",
    "            \"name\": \"Tech News\",\n",
    "            \"text\": \"\"\"\n",
    "            Apple announced today that its new iPhone 15 will feature USB-C charging,\n",
    "            marking a significant shift from the Lightning connector. The change comes\n",
    "            after pressure from the European Union's new charging regulations. The new\n",
    "            phones will also include improved cameras and faster processors. Industry\n",
    "            analysts expect this to boost sales significantly in the next quarter.\n",
    "            \"\"\"\n",
    "        },\n",
    "        {\n",
    "            \"name\": \"Code Comment\",\n",
    "            \"text\": \"\"\"\n",
    "            def process_data(input_list):\n",
    "                # This function takes a list of numbers and returns the average\n",
    "                # It handles empty lists by returning 0\n",
    "                if not input_list:\n",
    "                    return 0\n",
    "                return sum(input_list) / len(input_list)\n",
    "            \"\"\"\n",
    "        }\n",
    "    ]\n",
    "    \n",
    "    # Analyze each sample\n",
    "    for sample in samples:\n",
    "        print(f\"📋 Sample: {sample['name']}\")\n",
    "        print(\"-\" * 30)\n",
    "        \n",
    "        result = agent.analyze_text(sample[\"text\"].strip())\n",
    "        \n",
    "        print(f\"Category: {result['category']}\")\n",
    "        print(f\"Summary: {result['summary']}\")\n",
    "        print(\"Key Points:\")\n",
    "        for point in result['key_points']:\n",
    "            print(f\"  • {point}\")\n",
    "        print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13ea76e6-538a-4268-91db-91ddc5abee16",
   "metadata": {},
   "outputs": [],
   "source": [
    "demo_agent()\n",
    "print(\"\\n✅ Done!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0597dbfa-8b5f-4b72-abe1-d11b4dd57d13",
   "metadata": {},
   "source": [
    "# interactive mode:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8012f712-a1da-400c-999f-b4506a8fde36",
   "metadata": {},
   "source": [
    "The interactive_mode() function offers a simple command-line interface for real-time testing of a text analysis agent.\n",
    "\n",
    "It allows users to input freeform text and receive immediate feedback which includes a category classification, a summary, and key points extracted from the content.\n",
    "\n",
    "You can experiment with different types of input to see how the model interprets and summarizes information."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b0763e3-3916-46f1-95f1-3ba3902fd954",
   "metadata": {},
   "outputs": [],
   "source": [
    "def interactive_mode():\n",
    "    \"\"\"Interactive mode for testing with your own text.\"\"\"\n",
    "    print(\"🔄 Interactive Mode\")\n",
    "    print(\"=\" * 40)\n",
    "    \n",
    "    try:\n",
    "        agent = SimpleAnalysisAgent()\n",
    "    except ValueError as e:\n",
    "        print(e)\n",
    "        return\n",
    "    \n",
    "    print(\"Enter text to analyze (or 'quit' to exit):\")\n",
    "    \n",
    "    while True:\n",
    "        text = input(\"\\n> \")\n",
    "        \n",
    "        if text.lower() in ['quit', 'exit', 'q']:\n",
    "            break\n",
    "        \n",
    "        if len(text.strip()) < 10:\n",
    "            print(\"Please enter more text (at least 10 characters)\")\n",
    "            continue\n",
    "        \n",
    "        result = agent.analyze_text(text)\n",
    "        \n",
    "        print(f\"\\n📊 Results:\")\n",
    "        print(f\"Category: {result['category']}\")\n",
    "        print(f\"Summary: {result['summary']}\")\n",
    "        if result['key_points']:\n",
    "            print(\"Key Points:\")\n",
    "            for point in result['key_points']:\n",
    "                print(f\"  • {point}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb305a9a-382b-43d2-b8dc-8053a1c54b22",
   "metadata": {},
   "outputs": [],
   "source": [
    "interactive_mode()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
